package cn.bigfire.compiler.mytest;

import cn.bigfire.compiler.util.CharUtil;
import lombok.Data;
import lombok.SneakyThrows;
import org.junit.Test;

import java.io.CharArrayReader;
import java.util.ArrayList;
import java.util.List;

/**
 * 学英语的过程                       编译的过程
 * A,B,C...Z                        (char)
 * apple,dog                        (token)
 * my name is jack                  (expression)
 * 英语语法结构                       (ast语法树)
 * 英语小短文，段落，上下文             (VarScope作用域，Env环境)
 * 练习写作                          (目标代码生成)
 * <p>
 * 先理清楚 编译的步骤，
 * 1.读取字符串，然后一个字一个字的分析每一个字(char)
 * <p>
 * 2.把char组成词(token)        组词可不容易，
 * 首先我们要确定什么是一个词  一个空格算一个词吗？  a算一个词吗 ap,app,appl,apple哪些才是一个有效的词。
 * 其实我们知道 a(一个) app(应用的缩写) 和 apple(苹果)都可以算是一个词，但是程序不知道。
 * 状态：
 * 所以我们要定义一些状态，比如程序读到一个a的是我们标记他为(一个)词的状态，
 * 然后我们再读一个字符，如果后面是空格，标点符号，结束等，那就直接组词成功了，这个词就是a
 * 如果后面是p 我们标记为ID(未知状态) 然后继续往后读，就是读一个char判断一下状态。
 * 类型和属性：
 * 比如:apple，是一个单词,但是appla就不是一个单词。所以到底哪些才是词呢，需要我们先定义什么是词
 * 比如:我本定义apple(token.text=apple)是一个(token.type=N名词)(token.attr=苹果)
 * 而appla,(token.text=appla)(token.type=ID未定义)(token.attr=null),这种ID类型一般会有很多applb,applc,
 * 因为词有很多分类，如名词，动词，形容词，副词等等，所以我们也给token加上分类，tokenType,
 * 有的词有具体的意义如苹果，我们放在一个attr上，而没有意义的词attr就是空。
 * 由上面的过程，我们可以把一个char[]全部处理完，且每读一个都判断了一个状态。所以我们会得到一堆词List<Token>。
 * <p>
 * 3.根据List<Token>列表构建抽象语法树  这个也是一个大头
 * 和组词类似，首先我们要确定什么是一个句子， int a是不是一个句子？ int a = 5;  a+5 3+5 if(a=5){} 哪些才是有效的句子。
 * 首先我们要定于语法，我们来规定哪些是我们需要的合法的句子。然后我们需要描述这个语法的结构。我们怎么描述一个句子呢。
 * 主语+谓语+宾语  是合法的句子  这里的主语(I You He)，谓语(am is are)，宾语(jack)，我们一般会把替换为对应的词。
 * 关键字 变量名 = 数字;  是合法的句子  int aaa = 5; 这就是合法的句子了。这样其实就可以简单描述句子了。
 * 描述语法的方式有很多中，我们也会学一些，描述句子的方式如：上下文无关文法。巴斯范式等。
 * 他的样子大概长这样：
 * additive -> multiplicative | multiplicative + additive
 * multiplicative -> primary | primary * multiplicative
 * <p>
 * <p>
 * 根据语法树生成代码(中间代码也好，目标代码也好)
 */
public class JTestLexer {

    //展示遍历字符串中的每一个char
    @Test
    @SneakyThrows
    public void test001ReadChar() {
        String code1 = "int a = 50;";
        String code2 = "int 整数 = 50;";//整数这种中文字，一个中文字char占2个byte而已不影响他是一个char。

        for (char aChar : code1.toCharArray()) {
            System.out.print(aChar + " ");
        }
        System.out.println();
        for (char aChar : code2.toCharArray()) {
            System.out.print(aChar + " ");
        }
    }

    /**
     * 加状态，根据状态，进行继续读。for循环不太好用了，所以要用Reader类去封装charArray
     */
    @Test
    @SneakyThrows
    public void test002Char2Token() {
        //思考如何把一个个的char构建成一个token  char->token
        String code1 = "int a = 50;";
        StringBuilder tempSb = new StringBuilder();
        DfaState state = DfaState.INITIAL;
        for (char aChar : code1.toCharArray()) {
            if (state == DfaState.INITIAL) {
                if (CharUtil.isAlpha(aChar)) {
                    if (aChar == 'i') {//如果想再读一个，for直接遍历就不太好用了
                        tempSb.append(aChar);
                    }
                }
            }
        }
    }

    /**
     * Dfa状态值
     */
    enum DfaState {
        INITIAL             //初始化状态
        , ID                //标识符
        , KEY_WORD          //关键字状态
        , Plus              // +
        , Minus             // -
        , Star              // *
        , Slash             // /
        , Assignment         // =
        , SemiColon          // ;
        , LeftParen          // (
        , RightParen         // )
        , IntLiteral         // int
        , GT                 // >
        , GE                 // >=
        , Number             // 数字
    }

    enum TokenType {
        //声明语句lexer
         ID                //标识符
        , Number             // 数字
        , Assignment         // =
        , SemiColon          // ;
        //算数
        , Plus              // +
        , Minus             // -
        , Star              // *
        , Slash             // /
        //逻辑
        , LeftParen          // (
        , RightParen         // )
        , IntLiteral         // int
        , GT                 // >
        , GE                 // >=
    }

    //单词
    @Data
    public static class Token {
        private TokenType tokenType;
        private String text;

        public Token(TokenType tokenType, String text){
            this.tokenType = tokenType;
            this.text = text;
        }
        
    }

    /**
     * 加状态，根据状态，进行继续读。用Reader处理，同时把关键字看作Id lexer 后续在token中在根据判断是否为关键字
     */
    @Test
    @SneakyThrows
    public void test003Char2Token() {
        printTokens(tokenize1("int a = 50;"));
        printTokens(tokenize1("int a=50;"));
        printTokens(tokenize1("int a"));//循环结束了，但是tokenTmp中还有数据
    }

    @SneakyThrows
    public static List<Token> tokenize1(String code){
        List<Token> tokens = new ArrayList<>();
        StringBuilder tokenTmp = new StringBuilder();
        DfaState state = DfaState.INITIAL;
        CharArrayReader reader = new CharArrayReader(code.toCharArray());
        int ich = 0;
        char ch = 0;
        while ((ich = reader.read()) != -1) {
            ch = (char) ich;
            if (state == DfaState.INITIAL) {//第一个字符的情况
                if (CharUtil.isAlpha(ch)) {
                    state = DfaState.ID;
                    tokenTmp.append(ch);
                } else if (CharUtil.isDigit(ch)) {
                    state = DfaState.Number;
                    tokenTmp.append(ch);
                } else if ('=' == ch) {
                    state = DfaState.Assignment;

                    tokens.add(new Token(TokenType.Assignment, ch + ""));
                } else if (';' == ch) {
                    state = DfaState.SemiColon;

                    tokens.add(new Token(TokenType.SemiColon, ch + ""));
                } else if (CharUtil.isBlank(ch)) {
                    continue;//跳过空白字符
                }
            } else if (state == DfaState.ID) {
                if (CharUtil.isAlpha(ch)) {
                    state = DfaState.ID;
                    tokenTmp.append(ch);
                } else if (CharUtil.isDigit(ch)) {
                    state = DfaState.ID;
                    tokenTmp.append(ch);
                } else if ('=' == ch) {
                    state = DfaState.Assignment;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                    tokens.add(new Token(TokenType.Assignment, ch + ""));
                } else if (';' == ch) {
                    state = DfaState.SemiColon;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                    tokens.add(new Token(TokenType.SemiColon, ch + ""));
                } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                    state = DfaState.INITIAL;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                }
            } else if (state == DfaState.Number) {
                if (CharUtil.isAlpha(ch)) {
                    state = DfaState.ID;
                    tokenTmp.append(ch);
                } else if (CharUtil.isDigit(ch)) {
                    state = DfaState.Number;
                    tokenTmp.append(ch);
                } else if ('=' == ch) {
                    state = DfaState.Assignment;

                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                    tokens.add(new Token(TokenType.Assignment, ch + ""));
                } else if (';' == ch) {
                    state = DfaState.SemiColon;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                    tokens.add(new Token(TokenType.SemiColon, ch + ""));
                } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                    state = DfaState.INITIAL;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                }
            } else if (state == DfaState.Assignment) {
                if (CharUtil.isAlpha(ch)) {
                    state = DfaState.ID;
                    tokenTmp.append(ch);
                } else if (CharUtil.isDigit(ch)) {
                    state = DfaState.Number;
                    tokenTmp.append(ch);
                } else if ('=' == ch) {
                    state = DfaState.Assignment;

                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.Assignment, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                    tokens.add(new Token(TokenType.Assignment, ch + ""));
                } else if (';' == ch) {
                    state = DfaState.SemiColon;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.Assignment, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                    tokens.add(new Token(TokenType.SemiColon, ch + ""));
                } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                    state = DfaState.INITIAL;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.Assignment, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                }
            } else if (state == DfaState.SemiColon) {
                if (CharUtil.isAlpha(ch)) {
                    state = DfaState.ID;
                    tokenTmp.append(ch);
                } else if (CharUtil.isDigit(ch)) {
                    state = DfaState.Number;
                    tokenTmp.append(ch);
                } else if ('=' == ch) {
                    state = DfaState.Assignment;

                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.SemiColon, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                    tokens.add(new Token(TokenType.Assignment, ch + ""));
                } else if (';' == ch) {
                    state = DfaState.SemiColon;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.SemiColon, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                    tokens.add(new Token(TokenType.SemiColon, ch + ""));
                } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                    state = DfaState.INITIAL;
                    if (tokenTmp.toString().length() > 0) {
                        tokens.add(new Token(TokenType.SemiColon, tokenTmp.toString()));
                        tokenTmp = new StringBuilder();//重置
                    }
                }
            } else {
                System.out.println("未知状态");
            }
        }
        if (tokenTmp.toString().length() > 0) {
            if (state == DfaState.INITIAL) {

            } else if (state == DfaState.ID) {
                tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
            } else if (state == DfaState.Number) {
                tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
            } else if (state == DfaState.Assignment) {
                tokens.add(new Token(TokenType.Assignment, tokenTmp.toString()));
            } else if (state == DfaState.SemiColon) {
                tokens.add(new Token(TokenType.SemiColon, tokenTmp.toString()));
            }
        }

        return tokens;
    }

    /**
     * 打印token列表
     *
     * @param tokens token列表
     */
    public static void printTokens(List<Token> tokens) {
        System.out.println("---------------------");
        for (Token token : tokens) {
            System.out.println(token.text + "\t\t" + token.tokenType);
        }
        System.out.println("---------------------");
    }

    /**
     * lexer 的方法(lexer不关注语法,只做分词)
     * 1.有状态自动机。(最复杂，但状态最多，能力最强)
     * 2.使用tokenTmp判断状态。其实这种方式慢慢演变就会变为正则表达式的方式(描述能力客观，方便，毕竟常用)。
     * 3.code.split(" "),分割. （最简单,在一些测试代码中可以这么搞，但写解释器，不推荐使用）
     * 再给每个词确定类型，如有a=50这样连在一块的再分解，如有"hello和world"的再拼接。这种方式后续将不再合适()
     *
     *
     * int a = 50;  就这么一行因为加了状态和TokenType两个概念，写了一堆状态判断代码，
     * 写的过程中就在想 其实状态就是判断前面识别的数据是什么状态，所以状态可以根据tokenTemp判断状态
     * 这里其实有想过，如果直接用 code.split(" "),分割，再根据分出来的每个词进行类型区分，
     * 但是不合适，原因1:split会先读一遍字符串进行分割，然后还要再遍历一遍token，给token确定type，
     * 有一丝丝小开销，就是多遍历了一遍token。不过这个是小问题
     * 原因2: split分割会有问题，比如语句变成了 int a=50; a=50;中间没有空格就会把这个作为一个词。不合适。
     * 还有 String a= "hello world";  如果用空格分词，基本a=这个token还可以再处理一次，但是"hello和world"这俩就会被拆坏了。
     *
     */
    @Test
    @SneakyThrows
    public void test004Char2Token() {
        printTokens(tokenize2("int a = 50;"));
        printTokens(tokenize2("int a=50;"));
        printTokens(tokenize2("int a;"));
        printTokens(tokenize2("int a"));
    }

    @SneakyThrows
    public static List<Token> tokenize2(String code){
        List<Token> tokens = new ArrayList<>();
        StringBuilder tokenTmp = new StringBuilder();
        CharArrayReader reader = new CharArrayReader(code.toCharArray());
        int ich = 0;
        char ch = 0;
        while ((ich = reader.read()) != -1) {
            ch = (char) ich;

            if (tokenTmp.length() <= 0) {//空状态  初始状态
                if (CharUtil.isAlpha(ch)) {
                    tokenTmp.append(ch);
                } else if (CharUtil.isDigit(ch)) {
                    tokenTmp.append(ch);
                } else if ('=' == ch) {
                    tokens.add(new Token(TokenType.Assignment, ch + ""));
                } else if (';' == ch) {
                    tokens.add(new Token(TokenType.SemiColon, ch + ""));
                } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                    continue;//跳过空白开头
                }
            } else {//有数据状态
                if (CharUtil.isAlpha(tokenTmp.charAt(0))) {//字母开头
                    if (CharUtil.isAlpha(ch)) {
                        tokenTmp.append(ch);
                    } else if (CharUtil.isDigit(ch)) {
                        tokenTmp.append(ch);
                    } else if ('=' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Assignment, ch + ""));
                    } else if (';' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.SemiColon, ch + ""));
                    } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                    }
                } else if (CharUtil.isDigit(tokenTmp.charAt(0))) {//数字开头
                    if (CharUtil.isAlpha(ch)) {
                        tokenTmp.append(ch);
                    } else if (CharUtil.isDigit(ch)) {
                        tokenTmp.append(ch);
                    } else if ('=' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Assignment, ch + ""));
                    } else if (';' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.SemiColon, ch + ""));
                    } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                    }
                }
            }
        }

        if (tokenTmp.length() > 0) {
            char c = tokenTmp.charAt(0);
            if (CharUtil.isAlpha(tokenTmp.charAt(0))) {//字母开头
                tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
            } else if (CharUtil.isDigit(tokenTmp.charAt(0))) {
                tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
            } else if ('=' == ch) {
                tokens.add(new Token(TokenType.Assignment, tokenTmp.toString()));
            } else if (';' == ch) {
                tokens.add(new Token(TokenType.SemiColon, tokenTmp.toString()));
            }
        }

        return tokens;
    }



    /**
     * 上面两个方法测试了 变量定义语句的lexer
     * 下面我们来试试把算是表达式的+-/* （）也处理一下啊
     *
     */
    @Test
    @SneakyThrows
    public void test005Char2Token() {
        printTokens(tokenize3("int a = 5"));
        printTokens(tokenize3("int a = 3+5"));
        printTokens(tokenize3("2+4"));
        printTokens(tokenize3("1+3*5"));
        printTokens(tokenize3("(1+3)*5"));
    }

    @SneakyThrows
    public static List<Token> tokenize3(String code){
        List<Token> tokens = new ArrayList<>();
        StringBuilder tokenTmp = new StringBuilder();
        CharArrayReader reader = new CharArrayReader(code.toCharArray());
        int ich = 0;
        char ch = 0;
        while ((ich = reader.read()) != -1) {
            ch = (char) ich;
            if (tokenTmp.length() <= 0) {//空状态  初始状态
                if (CharUtil.isAlpha(ch)) {
                    tokenTmp.append(ch);
                } else if (CharUtil.isDigit(ch)) {
                    tokenTmp.append(ch);
                } else if ('=' == ch) {
                    tokens.add(new Token(TokenType.Assignment, ch + ""));
                } else if (';' == ch) {
                    tokens.add(new Token(TokenType.SemiColon, ch + ""));
                } else if ('+' == ch) {
                    tokens.add(new Token(TokenType.Plus, ch + ""));
                } else if ('-' == ch) {
                    tokens.add(new Token(TokenType.Minus, ch + ""));
                } else if ('*' == ch) {
                    tokens.add(new Token(TokenType.Star, ch + ""));
                } else if ('/' == ch) {
                    tokens.add(new Token(TokenType.Slash, ch + ""));
                } else if ('(' == ch) {
                    tokens.add(new Token(TokenType.LeftParen, ch + ""));
                } else if (')' == ch) {
                    tokens.add(new Token(TokenType.RightParen, ch + ""));
                } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                    continue;//跳过空白开头
                }
            } else {//有数据状态
                if (CharUtil.isAlpha(tokenTmp.charAt(0))) {//字母开头
                    if (CharUtil.isAlpha(ch)) {
                        tokenTmp.append(ch);
                    } else if (CharUtil.isDigit(ch)) {
                        tokenTmp.append(ch);
                    } else if ('=' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Assignment, ch + ""));
                    } else if (';' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.SemiColon, ch + ""));
                    } else if ('+' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Plus, ch + ""));
                    } else if ('-' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Minus, ch + ""));
                    } else if ('*' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Star, ch + ""));
                    } else if ('/' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Slash, ch + ""));
                    } else if ('(' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.LeftParen, ch + ""));
                    } else if (')' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.RightParen, ch + ""));
                    } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                    }

                } else if (CharUtil.isDigit(tokenTmp.charAt(0))) {//数字开头
                    if (CharUtil.isAlpha(ch)) {
                        tokenTmp.append(ch);
                    } else if (CharUtil.isDigit(ch)) {
                        tokenTmp.append(ch);
                    } else if ('=' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Assignment, ch + ""));
                    } else if (';' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.SemiColon, ch + ""));
                    }else if ('+' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Plus, ch + ""));
                    } else if ('-' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Minus, ch + ""));
                    } else if ('*' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Star, ch + ""));
                    } else if ('/' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.Slash, ch + ""));
                    } else if ('(' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.LeftParen, ch + ""));
                    } else if (')' == ch) {
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                        tokens.add(new Token(TokenType.RightParen, ch + ""));
                    } else if (CharUtil.isBlank(ch)) {//成功截取一个token
                        if (tokenTmp.toString().length() > 0) {
                            tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
                            tokenTmp = new StringBuilder();//重置
                        }
                    }
                }
            }
        }
        //结束时如果tokenTmp中还有数据，则加入token列表
        if (tokenTmp.length() > 0) {
            char c = tokenTmp.charAt(0);
            if (CharUtil.isAlpha(tokenTmp.charAt(0))) {//字母开头
                tokens.add(new Token(TokenType.ID, tokenTmp.toString()));
            } else if (CharUtil.isDigit(tokenTmp.charAt(0))) {
                tokens.add(new Token(TokenType.Number, tokenTmp.toString()));
            } else if ('=' == ch) {
                tokens.add(new Token(TokenType.Assignment, tokenTmp.toString()));
            } else if (';' == ch) {
                tokens.add(new Token(TokenType.SemiColon, tokenTmp.toString()));
            }else if ('+' == ch) {
                tokens.add(new Token(TokenType.Plus, tokenTmp.toString()));
            }else if ('-' == ch) {
                tokens.add(new Token(TokenType.Minus, tokenTmp.toString()));
            }else if ('*' == ch) {
                tokens.add(new Token(TokenType.Star, tokenTmp.toString()));
            }else if ('/' == ch) {
                tokens.add(new Token(TokenType.Slash, tokenTmp.toString()));
            }else if ('(' == ch) {
                tokens.add(new Token(TokenType.LeftParen, tokenTmp.toString()));
            }else if (')' == ch) {
                tokens.add(new Token(TokenType.RightParen, tokenTmp.toString()));
            }
        }
        return tokens;
    }






}
